<template>
  <a-modal :width="1300" v-model:visible="showEditDialog" title="提交入库" top="8vh" title-align="start" :on-before-ok="submitData" :ok-loading="submitLoading" :mask-closable="false" @cancel="closedDialog">
    <p style="margin-bottom: 10px">注意：一个申购单的明细放到一个入库单里面</p>
    <a-table
      class="table-normal-line s"
      ref="tableRef"
      row-key="planId"
      :data="purchaseOrders"
      :span-method="spanMethodAll"
      :scroll="{
        y: 'calc(84vh - 180px)',
      }"
      :columns="tableColumns"
      :expandable="expandable"
      :loading="tableLoading"
      :default-expand-all-rows="true"
      size="mini"
      :bordered="false"
      :pagination="false"
    >
      <template #columns>
        <a-table-column v-for="(item, index) of tableColumns" :fixed="item.fixed" :key="index" :align="item.align" :width="item.width" :title="item.title" :data-index="item.dataIndex">
          <template #title v-if="item.tip">
            <a-popover>
              <template #content>
                <p v-for="(str, i) in item.tip.split('--')" :key="i" style="max-width: 500px">{{ str }}</p>
              </template>
              <p>
                <span>{{ item.title }}</span>
                <icon-question-circle />
              </p>
            </a-popover>
          </template>

          <template v-if="item.dataIndex == 'sku'" #cell="{ record }">
            <div class="order-w flex">
              <div class="order-detail-item" style="width: 200px">
                <p>
                  <span class="label">申购单：</span>
                  <span class="highlight">{{ record.planNo }}</span>
                </p>
              </div>
              <div class="order-detail-item" style="width: 200px">
                <p>
                  <span class="label">申购方：</span>
                  <span>{{ record.salesmanDeptName }}</span>
                </p>
              </div>
              <div class="order-detail-item" style="width: 140px">
                <p><span class="label">申购人：</span>{{ record.salesmanName }}</p>
              </div>
              <div class="order-detail-item" style="width: 240px">
                <p><span class="label">收货仓：</span>{{ record.warehouseName }}({{ record.warehouseCode }})</p>
              </div>
            </div>
          </template>
        </a-table-column>
      </template>
      <template #expand-row="{ record }">
        <a-table class="table-two-line" :bordered="{ cell: true }" row-class="child-row" :show-header="false" row-key="id" :columns="tableColumns" :data="record.billItems" size="mini" :pagination="false">
          <template #columns>
            <a-table-column :width="10" />
            <a-table-column v-for="(item, index) of tableColumns" :key="index" :fixed="item.fixed" :align="item.align" :width="item.width" :title="item.title" :data-index="item.dataIndex">
              <template #cell="option">
                <!-- 产品 -->
                <div v-if="item.dataIndex == 'sku'" class="flex-c">
                  <ImgPopover :src="option.record.productImg">
                    <template #con>
                      <a-image width="50" height="50" fit="contain" :src="option.record.productImg" />
                    </template>
                  </ImgPopover>
                  <div style="margin-left: 5px; flex: 1">
                    <ShowSpuDetailBySku :val="option.record.sku" :showLimit="true" :rows="1" />
                    <TextLimit :val="getProductSpecs(option.record)" :rows="1" />
                  </div>
                </div>
                <!-- 出仓 -->
                <div v-else-if="item.dataIndex == 'outWarehouse'" class="cell" style="width: 140px">
                  <div class="flex-c">
                    <a-select v-model="option.record.warehouse" value-key="id" style="width: 120px" @change="changeWarehouse(option.record)">
                      <a-option :value="undefined" label="无需扣减库存" />
                      <a-option v-for="(warehouseInfo, j) in useBaseData.warehouseList" :key="j" :value="warehouseInfo" :label="warehouseInfo.warehouseName" />
                    </a-select>
                    <icon-double-down v-if="showBatchIcon(record.id, option.rowIndex)" class="edit-icon" @click="setGlobalWarehouse(option.record, option.rowIndex, record.id)" />
                  </div>
                  <p v-show="option.record.warehouse && option.record.warehouse.warehouseCode" style="font-size: 12px" class="highlight">现货库存：{{ getAmtAvailable(option.record) }}</p>
                </div>
                <!-- 入库数 -->
                <div v-else-if="item.dataIndex == 'warehouseAmt'" class="cell flex-c" style="width: 80px">
                  <a-input-number :precision="0" :min="0" v-model="option.record.warehouseAmt" style="width: 60px" placeholder="" hide-button @change="changeWarehouseAmt(option.record)" />
                  <icon-double-down v-if="showBatchIcon(record.id, option.rowIndex)" class="edit-icon" @click="setGlobalWarehouseAmt(option.record, option.rowIndex, record.id)" />
                </div>
                <!-- 主材重量 -->
                <div v-else-if="item.dataIndex == 'materialWeight'" class="cell flex-c" style="width: 80px">
                  <a-input-number :precision="2" :min="0" v-model="option.record.materialWeight" style="width: 60px" placeholder="" hide-button />
                  <icon-double-down v-if="showBatchIcon(record.id, option.rowIndex)" class="edit-icon" @click="setGlobal(option.record, 'materialWeight', option.rowIndex, record.id)" />
                </div>

                <!-- 材质金额 -->
                <span v-else-if="item.dataIndex == 'materialAmount'">￥{{ (Number(option.record.materialWeight || 0) * Number(option.record.materialPrice || 0)).toFixed(2) }}</span>
                <!-- 产品金额 -->
                <span v-else-if="item.dataIndex == 'productAmount'">￥{{ (Number(option.record.warehouseAmt || 0) * Number(option.record.productPrice || 0)).toFixed(2) }}</span>
                <!-- 工费 -->
                <span v-else-if="item.dataIndex == 'laborAmount'">￥{{ (Number(option.record.warehouseAmt || 0) * Number(option.record.laborPrice2 || 0)).toFixed(2) }}</span>
                <!-- 其他费用 -->
                <div v-else-if="item.dataIndex == 'otherAmount'" class="cell flex-c" style="width: 80px">
                  <a-input-number :precision="2" :min="0" v-model="option.record.otherAmount" style="width: 60px" placeholder="" hide-button />
                  <icon-double-down v-if="showBatchIcon(record.id, option.rowIndex)" class="edit-icon" @click="setGlobal(option.record, 'otherAmount', option.rowIndex, record.id)" />
                </div>
                <!-- 合计金额 -->
                <span v-else-if="item.dataIndex == 'totalAmount'">￥{{ getTotalAmount(option.record).toFixed(2) }}</span>
                <!-- 税率 -->
                <div v-else-if="item.dataIndex == 'rate'" class="cell flex-c" style="width: 160px">
                  <a-select v-model="option.record.priceType" size="medium" style="width: 70px">
                    <a-option :value="0">不含税</a-option>
                    <a-option :value="1">含税</a-option>
                  </a-select>
                  <a-input-number v-model="option.record.rate" style="width: 60px" hide-button placeholder="" />
                  <span>%</span>
                  <icon-double-down v-if="showBatchIcon(record.id, option.rowIndex)" class="edit-icon" @click="setGlobal(option.record, 'rate', option.rowIndex, record.id)" />
                </div>
                <!-- 税金 -->
                <span v-else-if="item.dataIndex == 'rateAmount'">￥{{ ((getTotalAmount(option.record) * Number(option.record.rate || 0)) / 100).toFixed(2) }}</span>
                <!-- 单件货值 -->
                <span v-else-if="item.dataIndex == 'value'">￥{{ getTotalValue(option.record).toFixed(2) }}</span>

                <p v-else-if="['materialPrice', 'laborPrice2', 'productPrice'].includes(item.dataIndex)">￥{{ option.record[item.dataIndex] }}</p>
                <p v-else>{{ option.record[item.dataIndex] }}</p>
              </template>
            </a-table-column>
          </template>
        </a-table>
      </template>
    </a-table>
  </a-modal>
</template>
<script lang="ts" setup>
  import { ref, onMounted } from 'vue'
  import { Message } from '@arco-design/web-vue'
  import { submitPurchaseReceipt, getPurchaseItemByPlan } from '@/api/purchaseApplication'
  import { findInventoryBatch } from '@/api/inventory'
  import useBaseDataStore from '@/store/modules/base-data'
  import { parseJson } from '@/utils'
  import { cloneDeep } from 'lodash-es'

  onMounted(() => {
    getWareHouseList()
    setDefaultData()
  })
  const emit = defineEmits(['closed', 'success'])
  const props = defineProps({
    isShow: {
      type: Boolean,
      default: false,
    },
    list: {
      type: Array,
      default: () => [],
    },
  })
  const tableColumns: Array<any> = [
    {
      title: '产品',
      dataIndex: 'sku',
      width: 160,
    },
    {
      title: '扣减库存',
      dataIndex: 'outWarehouse',
      tip: '如果需要扣减本地仓库的库存就需要选择一个仓库。这里的库存扣减并非实时反应的，系统每天凌晨1点统一扣减天一的库存。',
      width: 160,
    },
    {
      title: '申购数量',
      dataIndex: 'planAmt',
      width: 40,
    },
    {
      title: '材质单价(元/g)',
      dataIndex: 'materialPrice',
      tip: '材质单价，取采购参数材质对应的报价，该报价每天都有变化，取申购订单被接单日的材质报价',
      width: 60,
    },

    {
      title: '产品单价',
      dataIndex: 'productPrice',
      tip: '产品单价：单个产品的成本价，默认值从该申购单关联的采购单上获取',
      width: 60,
    },
    {
      title: '工费单价',
      dataIndex: 'laborPrice2',
      tip: '工费是指采购人员的服务费，是在申购单接单时确定好的，在此无法修改',
      width: 60,
    },
    {
      title: '入库数',
      dataIndex: 'warehouseAmt',
      tip: '入库数量：如果需要扣减库存的，入库数量必须小于等于现货库存数',
      width: 100,
    },
    {
      title: '入库材质重(g)',
      dataIndex: 'materialWeight',
      tip: '金银等贵金属首饰类产品是按材质重量计算价格的，所以入库时必须要有材质重量。默认值=关联的采购订单上的单件材质重量*入库数量',
      width: 110,
    },
    {
      title: '材质金额',
      dataIndex: 'materialAmount',
      tip: '材质金额=材质单价*入库材质重',
      width: 80,
    },
    {
      title: '产品金额',
      dataIndex: 'productAmount',
      tip: '产品费用=产品单价*入库数',
      width: 80,
    },
    {
      title: '工费',
      dataIndex: 'laborAmount',
      tip: '工费=工费单价*入库数',
      width: 80,
    },
    {
      title: '其他费用',
      dataIndex: 'otherAmount',
      tip: '其他费用：本次采购入库产生的其他费用',
      width: 100,
    },
    {
      title: '合计金额',
      dataIndex: 'totalAmount',
      tip: '合计金额=材质金额+产品金额+其他费用+工费',
      width: 80,
    },
    {
      title: '税率',
      dataIndex: 'rate',
      tip: '是否含税和税率，默认从绑定的采购单上获取',
      width: 180,
    },
    {
      title: '税金',
      dataIndex: 'rateAmount',
      tip: '税金=合计金额*税率',
      width: 80,
    },
    {
      title: '单件货值',
      dataIndex: 'value',
      tip: '含税单件货值=（合计金额-税金）/入库数量 --不含税单件货值=合计金额/入库数量',
      width: 80,
    },
  ]

  const expandable = ref<any>({
    title: '',
    defaultExpandAllRows: true,
    expandedRowKeys: [],
    width: 10,
  })
  const showEditDialog = ref(props.isShow)
  const purchaseOrders = ref<Array<any>>([])
  const submitLoading = ref(false)
  const useBaseData = useBaseDataStore()
  const tableLoading = ref(false)
  const queryInventoryMap = ref<any>({})
  const purchaseItemMap = ref<any>({})

  // 获取仓库列表
  async function getWareHouseList() {
    await useBaseData.getWareHouseList()
  }
  // 添加初始化数据
  async function setDefaultData() {
    // 一个申购单的明细放到一个入库单里面，需要根据申购单号进行组合
    let _list = cloneDeep(props.list)
    const orderMap: any = {}
    let itemIds: Array<string> = []
    _list.forEach((el: any) => {
      if (!orderMap[el.planNo]) {
        orderMap[el.planNo] = {
          planId: el.billId,
          planNo: el.planNo,
          salesmanName: el.salesmanName,
          salesmanId: el.salesmanId,
          salesmanDeptName: el.salesmanDeptName,
          salesmanDeptId: el.salesmanDeptId,
          warehouseName: el.warehouseName,
          warehouseCode: el.warehouseCode,
          companyName: el.companyName,
          billItems: [],
        }
      }
      el.priceType = 0
      el.planItemId = el.id
      el.laborPrice2 = el.laborPriceType === 1 ? el.laborPrice : Number(el.productPrice || 0) * Number((el.laborRate || 0) / 100)
      orderMap[el.planNo].billItems.push(el)
      itemIds.push(el.id)
    })
    purchaseOrders.value = Object.values(orderMap)
    getQueryInventory()
    getPurchaseItem(itemIds)
    expandable.value.expandedRowKeys = purchaseOrders.value.map((el: any) => el.planId)
  }
  // 获取关联的采购订单信息
  async function getPurchaseItem(ids: Array<string>) {
    purchaseItemMap.value = {}
    const res: any = await getPurchaseItemByPlan({ ids })
    let list = res?.data || []
    list.forEach((el: any) => {
      purchaseItemMap.value[el.planItemId] = el
    })
    // 设置默认入库数，入库材质重和税率
    purchaseOrders.value.forEach((item: any) => {
      item.billItems.forEach((el: any) => {
        let purchaseItemInfo = purchaseItemMap.value[el.id]
        if (purchaseItemInfo) {
          el.warehouseAmt = purchaseItemInfo.deliveryRealAmt
          el.materialWeight = purchaseItemInfo.materialRealWeight
          el.priceType = purchaseItemInfo.priceType
          el.rate = purchaseItemInfo.rate
        }
      })
    })
  }
  // 修改入库数
  function changeWarehouseAmt(item: any) {
    // 有关联采购订单的取采购单的单个入库材质重量
    let purchaseItemInfo = purchaseItemMap.value[item.id]
    if (purchaseItemInfo) {
      item.materialWeight = Number(purchaseItemInfo.singleMaterialWeight || 0) * item.warehouseAmt
    }
  }
  // 全局设置入库数
  function setGlobalWarehouseAmt(item: any, rowIndex: number, parentId: string) {
    setGlobal(item, 'warehouseAmt', rowIndex, parentId)
    // 修改入库数，需要重新计算材质重
    purchaseOrders.value.forEach((el: any) => {
      el.billItems.forEach((item: any) => {
        changeWarehouseAmt(item)
      })
    })
  }
  // 获取可用库存
  async function getQueryInventory() {
    queryInventoryMap.value = {}
    let inventoryItems: Array<any> = []
    purchaseOrders.value.forEach((el: any) => {
      el.billItems.forEach((item: any) => {
        if (item.warehouse?.warehouseCode) {
          inventoryItems.push({
            warehouseCode: item.warehouse.warehouseCode,
            sku: item.sku,
            shopId: item.purchaseCompanyId + 'shareshop',
          })
        }
      })
    })
    if (!inventoryItems.length) return
    const res = await findInventoryBatch({ inventoryItems })
    let list = res?.data?.inventoryItems || []
    list.forEach((el: any) => {
      let key = el.shopId + el.sku + el.warehouseCode
      queryInventoryMap.value[key] = el
    })
  }
  // 切换出库仓
  function changeWarehouse(item: any) {
    if (!item.warehouse?.warehouseCode) {
      return
    }
    getQueryInventory()
  }
  // 全局设置出库仓
  function setGlobalWarehouse(item: any, rowIndex: number, parentId: string) {
    setGlobal(item, 'warehouse', rowIndex, parentId)
    getQueryInventory()
  }
  // 获取可用库存值
  function getAmtAvailable(item: any) {
    let shopId = item.purchaseCompanyId + 'shareshop'
    let key = shopId + item.sku + item.warehouse?.warehouseCode
    return queryInventoryMap.value[key]?.amtAvailable || 0
  }
  // 合并单元格
  function spanMethodAll(option: any) {
    let { column } = option
    if (column.dataIndex === 'sku') {
      return { rowspan: 1, colspan: 16 }
    }
  }

  //设置全局
  async function setGlobal(item: any, key: string, rowIndex: number, parentId: string) {
    let parentIndex = purchaseOrders.value.findIndex((el: any) => el.id === parentId)
    const newVal = item[key]
    purchaseOrders.value.forEach((el: any, index: number) => {
      if (index === parentIndex) {
        el.billItems.forEach((child: any, j: number) => {
          if (j > rowIndex) child[key] = newVal
        })
      } else if (index > parentIndex) {
        el.billItems.forEach((child: any) => {
          child[key] = newVal
        })
      }
    })
  }

  // 是否显示批量编辑按钮
  function showBatchIcon(parentId: string, childIndex: number) {
    let parentIndex = purchaseOrders.value.findIndex((el: any) => el.id === parentId)
    let parentLen = purchaseOrders.value.length
    return !(parentIndex === parentLen - 1 && childIndex === purchaseOrders.value[parentIndex].billItems.length - 1)
  }
  // 获取合计金额
  function getTotalAmount(row: any) {
    let materialAmount = Number(row.materialWeight || 0) * Number(row.materialPrice || 0)
    let productAmount = Number(row.warehouseAmt || 0) * Number(row.productPrice || 0)
    let laborAmount = Number(row.warehouseAmt || 0) * Number(row.laborPrice2 || 0)
    let otherAmount = Number(row.otherAmount || 0)
    return materialAmount + productAmount + laborAmount + otherAmount
  }
  // 获取单件货值
  function getTotalValue(row: any) {
    let totalAmount = getTotalAmount(row)
    let rateAmount = row.priceType === 0 ? 0 : (totalAmount * Number(row.rate || 0)) / 100
    return row.warehouseAmt ? (totalAmount - rateAmount) / row.warehouseAmt : 0
  }
  // 关闭
  function closedDialog() {
    showEditDialog.value = false
    emit('closed')
  }
  // 保存
  async function submitData() {
    let receiptParams: Array<any> = []
    let flag = false
    purchaseOrders.value.forEach((el: any) => {
      let obj: any = {
        planId: el.planId,
      }
      obj.billItems = el.billItems.map((item: any) => {
        let billObj: any = {
          deductionType: 0,
          materialWeight: item.materialWeight,
          otherAmount: item.otherAmount,
          planId: el.planId,
          id: item.id,
          planItemId: item.planItemId,
          priceType: item.priceType,
          productPrice: item.productPrice,
          rate: item.rate,
          warehouseAmt: item.warehouseAmt,
        }
        if (item.warehouse?.warehouseCode) {
          billObj.deductionType = 1
          billObj.outWarehouseCode = item.warehouse.warehouseCode
          billObj.outWarehouseName = item.warehouse.warehouseName
          //有选择扣减库存仓的时候需要判断入库数是否超过可用库存
          let amtAvailable = getAmtAvailable(item)
          if (billObj.warehouseAmt > amtAvailable) {
            flag = true
          }
        }
        return billObj
      })
      receiptParams.push(obj)
    })
    if (flag) {
      Message.error('入库数量必须小于等于现货库存数')
      return false
    }
    let res: any = await submitPurchaseReceipt({ receiptParams })
    if (!res) return false
    Message.success('提交成功')
    emit('success')
    closedDialog()
  }
  // 显示sku规格
  function getProductSpecs(item: any) {
    let productSpecs = item.productSpecs ? parseJson(item.productSpecs, []) : []
    return productSpecs.map((el: any) => el.valueCn)?.join('*') || '--'
  }
</script>
<style lang="less" scoped>
  .header {
    font-size: 14px;
    font-weight: bold;
    margin-bottom: 20px;
    border-left: 3px solid rgba(var(--primary-6), 0.5);
    padding-left: 10px;
    .title {
      margin-right: 30px;
      width: 90px;
    }
  }
  :deep(.arco-table-td) {
    background-color: var(--color-fill-1);
    .arco-select-view-single {
      padding: 0 5px;
    }
    .arco-input-wrapper {
      padding: 0 5px;
    }
    .arco-select-view-value {
      font-size: 12px !important;
      min-height: 26px;
    }
    .arco-input {
      font-size: 12px !important;
    }
  }
  :deep(.arco-table-tr-expand) {
    .arco-table-cell {
      padding: 0;
    }
    .arco-table {
      margin: 0 !important;
      .arco-table-td {
        border-bottom: 1px solid var(--color-neutral-3);
      }
    }
    background-color: #fff !important;
  }
  :deep(.child-row) {
    .arco-table-cell {
      padding: 2px 5px;
    }
  }
  :deep(.arco-table-tr-expand .arco-table-td) {
    background-color: #fff !important;
    border-bottom: none;
  }
  :deep(.arco-table-tr-expand tr:hover .arco-table-td) {
    background-color: var(--color-fill-1) !important;
  }
  :deep(.arco-table-expand .arco-table-cell) {
    display: none;
  }
  :deep(.arco-tabs-nav-tab) {
    background-color: #fff;
  }
  .order-w {
    color: #666;
    flex: 1;
    .order-detail-item {
      width: 200px;
    }
  }
  .price-type {
    font-size: 12px;
    transform: scale(0.82);
    position: relative;
    left: -4px;
  }
  .edit-icon {
    font-size: 16px;
    margin-left: 5px;
    cursor: pointer;
  }
</style>
